using System;
using System.Collections.Generic;
using System.Text;

using Outlook = Microsoft.Office.Interop.Outlook;
using System.Runtime.InteropServices;
using System.Drawing;
using Microsoft.SoftwarePlusServices.ReferenceBits.OutlookPlusServices;

namespace Microsoft.SoftwarePlusServices.ReferenceBits.OutlookPlusServices.Regions
{
    ///
    /// <summary>
    /// Manages the retrieval of form region information such as icons, manifests, and the form regions themselves.  
    /// If a form is opened, its lifetime is tracked in a dictionary of open form regions.
    /// </summary>
    ///
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1408:DoNotUseAutoDualClassInterfaceType"), ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [GuidAttribute("841D1958-FC4A-404b-A010-AD0D5D86B200")]
    [ProgId("Microsoft.SoftwarePlusServices.ReferenceBits.OutlookPlusServices.FormRegionManager")]
    public sealed class FormRegionManager : Outlook.FormRegionStartup
    {

        #region Private Fields
        private Dictionary<string, Regions.IItemRegion> _openRegions =
            new Dictionary<string, Regions.IItemRegion>();

        private List<ItemRegionInfo> _itemRegions = new List<ItemRegionInfo>();

        static private System.Resources.ResourceManager _resourceManager;

        #endregion

        /// <summary>
        /// Allows setting of which ResourceManager should be used for this factory
        /// </summary>
        public System.Resources.ResourceManager ResourceManager
        {
            set { _resourceManager = value; }
        }

        /// <summary>
        /// Adds an ItemRegion to the list of form Regions
        /// </summary>
        /// <param name="itemRegion">object which implements a FormRegion</param>
        /// <param name="tag">tag identifying the FormRegion</param>
        public void AddItemRegion(IItemRegion itemRegion, string tag)
        {
            _itemRegions.Add(new ItemRegionInfo(itemRegion, tag));
        }

        #region _FormRegionStartup Methods
        ///
        /// <summary>
        /// Manages the creation of new form regions by attaching a close event handler
        /// and adding them to the list of open regions when they are shown.
        /// </summary>
        /// <param name="FormRegion">A reference to the form region being shown.</param>
        ///
        void Outlook._FormRegionStartup.BeforeFormRegionShow(Outlook.FormRegion FormRegion)
        {
            foreach (ItemRegionInfo regionInfo in _itemRegions)
            {
                if (FormRegion.InternalName == regionInfo.Tag)
                {
                    //
                    // connect the item region code behind to the form region 
                    // and allow it to customize its properties
                    //
                    regionInfo.ItemRegion.Customize(FormRegion, FormRegion.Item);

                    //
                    // Attach the close event so that when the item region closes
                    // it will do its cleanup and then call our FormRegionClosed delegate
                    // to remote it from the list of open regions
                    //
                    regionInfo.ItemRegion.Close += new EventHandler(FormRegionClosed);

                    // add to the list of regions
                    if (!_openRegions.ContainsKey(regionInfo.ItemRegion.GUID))
                        _openRegions.Add(regionInfo.ItemRegion.GUID, regionInfo.ItemRegion);
                    break;
                }
            }
        }

        ///
        /// <summary>
        /// When a form region is closed, it is removed from the list of open regions.
        /// </summary>
        /// <param name="sender">The object sending the event.</param>
        /// <param name="e">Event arguments from the sender.</param>
        ///
        private void FormRegionClosed(object sender, EventArgs e)
        {
            _openRegions.Remove((sender as IItemRegion).GUID);
        }

        ///
        /// <summary>
        /// Retrieves the icon used when displaying the form region.
        /// </summary>
        /// <param name="FormRegionName">The name of the form region needing an icon.</param>
        /// <param name="LCID">The Locale of the current instance of Outlook.</param>
        /// <param name="Icon">The type of icon needed.</param>
        /// <returns>A byte arrray containing the contents of an ico file.  Null if no icon is provided.</returns>
        ///
        object Outlook._FormRegionStartup.GetFormRegionIcon(string FormRegionName, int LCID, Outlook.OlFormRegionIcon Icon)
        {
            object retVal = _resourceManager.GetObject(FormRegionName + "_ICON");
            return (retVal);
        }

        ///
        /// <summary>
        ///     Returns the manifest for the requested region.  The manifest is used by Outlook to configure the form region.
        /// </summary>
        /// <param name="FormRegionName">The name of the form region needing a manifest.</param>
        /// <param name="LCID">The Locale of the current instance of Outlook.</param>
        /// <returns>A string containing the xml of the region manifest.</returns>
        ///
        object Microsoft.Office.Interop.Outlook._FormRegionStartup.GetFormRegionManifest(string FormRegionName, int LCID)
        {
            object retVal = _resourceManager.GetObject(FormRegionName + "_MANIFEST");
            return (retVal);
        }

        ///
        /// <summary>
        /// Retrieves the actual form region storage object for the form region.  The object is expected
        /// as a byte array of a .ofs file generated by the Outlook form designer.
        /// </summary>
        /// <param name="FormRegionName">The name of the form region needing a form region.</param>
        /// <param name="Item">The Outlook item that will be displayed in this form region.</param>
        /// <param name="LCID">The Locale of the current instance of Outlook.</param>
        /// <param name="FormRegionMode">The mode of the form region to retrieve.  Can be read, compose, or preview.</param>
        /// <param name="FormRegionSize">The size of the form region to retrieve.  Can be seperate or adjoining.</param>
        /// <returns>A byte array containing the form region .ofs file generated in the Outlook form designer.</returns>
        ///
        object Microsoft.Office.Interop.Outlook._FormRegionStartup.GetFormRegionStorage(
            string FormRegionName, object Item, int LCID, Microsoft.Office.Interop.Outlook.OlFormRegionMode FormRegionMode, Microsoft.Office.Interop.Outlook.OlFormRegionSize FormRegionSize)
        {
            return (_resourceManager.GetObject(FormRegionName));
        }
        #endregion
    }
}
